feat(dify-plugin): port external PRs#28
Conversation
…rm fields Ports the still-relevant parts of PR #1 from the archived daytona/dify-plugin. The SDK-compat list() call and SDK version pin were already handled by the monorepo cubic-review fixes, so this ports the remainder: widen get_preview_url to ports 1-65535 (was 3000-9999), and treat blank auto_stop_interval/cpu/memory/disk form values as unset so Dify's empty-string inputs never reach to_int(). Original work by @hjpinheiro (daytona/dify-plugin#1). Co-authored-by: hpiclaranet <hpiclaranet@users.noreply.github.com> Signed-off-by: Mislav Ivanda <mislavivanda454@gmail.com>
Ports PR #2 from the archived daytona/dify-plugin: a shared MAX_FILE_SIZE (100 MB) in _client.py, checked against file.blob before upload and against get_file_info().size (pre-download) plus content length (post-download) — preventing a large file from OOM-crashing the plugin daemon. Original work by @hjpinheiro (daytona/dify-plugin#2). Co-authored-by: hpiclaranet <hpiclaranet@users.noreply.github.com> Signed-off-by: Mislav Ivanda <mislavivanda454@gmail.com>
… error handling Ports PR #3 from the archived daytona/dify-plugin: build_client() now caches one Daytona instance per credential hash (the plugin daemon is long-lived, so this avoids re-creating an HTTP session on every tool call), and get_sandbox() also maps a generic DaytonaError to a clear ValueError. Omitted the PR's unused module logger to keep the file lint-clean. Original work by @hjpinheiro (daytona/dify-plugin#3). Co-authored-by: hpiclaranet <hpiclaranet@users.noreply.github.com> Signed-off-by: Mislav Ivanda <mislavivanda454@gmail.com>
Ports PR #4 from the archived daytona/dify-plugin: replaces the session-based create_session/execute_session_command/delete_session dance with a single sandbox.process.exec() call, adding optional working directory, environment variables (JSON), and timeout. Uses the monorepo's to_int() for the timeout param and guards a missing command. Original work by @hjpinheiro (daytona/dify-plugin#4). Co-authored-by: hpiclaranet <hpiclaranet@users.noreply.github.com> Signed-off-by: Mislav Ivanda <mislavivanda454@gmail.com>
Ports PR #5 from the archived daytona/dify-plugin: when Python code produces charts (matplotlib/etc.), the Daytona SDK returns them as base64 PNGs in response.artifacts.charts. These were previously discarded; now each is decoded and yielded as an image/png blob message so users see rendered charts in Dify, with chart metadata added to the JSON result. Original work by @hjpinheiro (daytona/dify-plugin#5). Co-authored-by: hpiclaranet <hpiclaranet@users.noreply.github.com> Signed-off-by: Mislav Ivanda <mislavivanda454@gmail.com>
Ports PR #6 from the archived daytona/dify-plugin: adds list_files, read_file, write_file, search_files and find_in_files tools (with yaml manifests) for working with files inside a sandbox, and registers them in provider/daytona.yaml. Original work by @hjpinheiro (daytona/dify-plugin#6). Co-authored-by: hpiclaranet <hpiclaranet@users.noreply.github.com> Signed-off-by: Mislav Ivanda <mislavivanda454@gmail.com>
Ports PR #7 from the archived daytona/dify-plugin: adds git_clone (clone a repo into a sandbox), list_sandboxes (list with state filter), and manage_sandbox (start/stop/archive), plus yaml manifests, registered in provider/daytona.yaml. Original work by @hjpinheiro (daytona/dify-plugin#7). Co-authored-by: hpiclaranet <hpiclaranet@users.noreply.github.com> Signed-off-by: Mislav Ivanda <mislavivanda454@gmail.com>
…ervice_logs) Ports PR #8 from the archived daytona/dify-plugin: start_service runs a long-lived command in an async session, and get_service_logs retrieves its output — enabling background processes (web servers, watchers) in a sandbox. Registered in provider/daytona.yaml. Original work by @hjpinheiro (daytona/dify-plugin#8). Co-authored-by: hpiclaranet <hpiclaranet@users.noreply.github.com> Signed-off-by: Mislav Ivanda <mislavivanda454@gmail.com>
Verifying the ported PRs against the Daytona SDK reference surfaced drift vs the pinned 0.193+ (the fork targeted ~0.187): - start_service: SessionExecuteRequest field is run_async, not var_async. - find_in_files: fs.find_files returns a flat list[Match] (.file/.line/.content), not nested r.matches/r.file.path. - search_files: fs.search_files returns SearchFilesResponse (.files), not a list (len()/JSON on it would fail). - list_sandboxes: remove unused SandboxState import (lint error). - run_code: chart PNGs are on chart.png (chart.elements are data points, not images) — the old path delivered zero charts; also serialize the ChartType enum. Signed-off-by: Mislav Ivanda <mislavivanda454@gmail.com>
There was a problem hiding this comment.
All reported issues were addressed across 30 files
You’re at about 93% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.
Tip: instead of fixing issues one by one fix them all with cubic
Re-trigger cubic
cubic review: read_file bypassed the size guard (loaded arbitrary files into memory) and write_file could upload past the shared limit; both now check size before/after transfer. upload_file now prechecks file.size metadata before materializing the blob. write_file also drops the empty-file second get_file_info lookup in favor of len(encoded). Signed-off-by: Mislav Ivanda <mislavivanda454@gmail.com>
…ommit_id is set cubic review: embedded HTTPS userinfo in the repo URL was echoed back in both JSON and text output — now redacted (raw URL still used for the clone). Also stop sending/reporting branch when commit_id is provided (commit produces a detached checkout and overrides branch). Signed-off-by: Mislav Ivanda <mislavivanda454@gmail.com>
…te limit cubic review: ListSandboxesQuery.limit is the page size, and list(daytona.list(...)) paged through the whole account regardless of limit. Use itertools.islice to collect at most 'limit' items, and validate limit via to_int as a positive whole number (rejecting fractional/non-positive values). Signed-off-by: Mislav Ivanda <mislavivanda454@gmail.com>
…ndbox cubic review: archiving a running sandbox failed because Daytona requires it to be stopped first — the archive action now stops (which blocks until fully stopped) unless already stopped/archived. Switch both lookups to _client.get_sandbox for consistent not-found errors, and drop the redundant wait_for_sandbox_start() since Sandbox.start() already blocks until ready. Signed-off-by: Mislav Ivanda <mislavivanda454@gmail.com>
…ch failure cubic review: two services started in the same sandbox within one second shared session id svc-<int(time.time())>, so the second create_session collided. Use a UUID-based id. Also delete the freshly created session if execute_session_command fails so failed launches don't accumulate stale sessions. Signed-off-by: Mislav Ivanda <mislavivanda454@gmail.com>
cubic review: negative timeouts were forwarded to the SDK where they become an invalid command/HTTP timeout. Validate timeout >= 0 (0/empty still means no timeout) so callers get a deterministic error. Signed-off-by: Mislav Ivanda <mislavivanda454@gmail.com>
cubic review: report a neutral '(no output)' instead of '(no output yet)' for completed silent commands, and only insert a newline between stdout and stderr when both are non-empty and stdout doesn't already end with one (avoids a leading newline for stderr-only output and doubled newlines). Signed-off-by: Mislav Ivanda <mislavivanda454@gmail.com>
cubic review: the cache key concatenated api_key/api_url with a single ':' separator, so distinct pairs could hash to the same entry and reuse another credential set's client. Length-prefix each field before hashing. Signed-off-by: Mislav Ivanda <mislavivanda454@gmail.com>
cubic review, documentation-only fixes: - run_command: describe combined 'output' contract (stdout+stderr) in the README feature list and Tool Reference, and document cwd/env_vars/timeout inputs; timeout help now explains empty = Daytona default and 0 = no timeout - git_clone: set the private-repo password/token to form: form so it is a preset encrypted credential rather than an LLM-inferred argument - start_service: tell the model to bind previewable services to 0.0.0.0 so get_preview_url is reachable - find_in_files: describe the pattern as a text pattern (SDK/Toolbox does not document regex support) - get_preview_url: README port range corrected to 1-65535 to match the schema Signed-off-by: Mislav Ivanda <mislavivanda454@gmail.com>
cubic review: run_code now emits generated charts as PNG blobs and adds charts_count/charts JSON fields, but neither the tool description nor the README output contract mentioned them. Document both so users and the LLM can discover the behavior. Signed-off-by: Mislav Ivanda <mislavivanda454@gmail.com>
There was a problem hiding this comment.
All reported issues were addressed across 16 files (changes from recent commits).
You’re at about 95% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
cubic review follow-up: _redact_url used parts.hostname (which strips IPv6 brackets, turning [::1]:8080 into the malformed ::1:8080) and parts.port (which can raise on a malformed port, outside the try). Keep the netloc after the last '@' instead, which drops only the userinfo while preserving valid host:port / IPv6 syntax. Signed-off-by: Mislav Ivanda <mislavivanda454@gmail.com>
cubic review follow-up: archive() requires a stopped sandbox, so calling it on an already-archived sandbox can fail. Treat 'archived' as idempotent success and only stop/archive other states. Signed-off-by: Mislav Ivanda <mislavivanda454@gmail.com>
This work is based on the PRs from the previous standalone Dify plugin repo which were created by @hjpinheiro.
Summary by cubic
Ports the remaining external Dify plugin work and adds file, git, lifecycle, and background-service tools for Daytona sandboxes. Improves reliability and performance with a cached client, safer cloning/archiving and file transfers, broader port validation, and richer outputs.
New Features
list_files,read_file,write_file,search_files,find_in_files).git_clone,list_sandboxes,manage_sandbox).start_service,get_service_logs).run_commanduses process.exec with optionalcwd,env_vars, andtimeout;run_codeemits chart PNGs as image blobs and adds chart metadata.Performance & Reliability
git_clonewithout breaking IPv6/port URLs; drop branch whencommit_idis set; validate and caplist_sandboxesvialimit; stop before archiving and treat already-archived sandboxes as a no-op; unique session IDs and cleanup if launch fails instart_service; reject negativerun_commandtimeouts; clearerget_service_logsoutput joining.get_preview_url; treat blank numeric fields increate_sandboxas unset.provider/daytona.yaml.Written for commit 61d38ce. Summary will update on new commits.